
#ifndef __AUDIO_H
#define __AUDIO_H

#ifdef __cplusplus
extern "C" {
#endif

#include "encode.h"
#include <stdio.h>

#define READSIZE 1024

/* In WIN32, the following bitmap can be found in sdk\inc\ksmedia.h and sdk\inc\mmreg.h: */

#ifndef SPEAKER_FRONT_LEFT
#	define SPEAKER_FRONT_LEFT             0x1
#	define SPEAKER_FRONT_RIGHT            0x2
#	define SPEAKER_FRONT_CENTER           0x4
#	define SPEAKER_LOW_FREQUENCY          0x8
#	define SPEAKER_BACK_LEFT              0x10
#	define SPEAKER_BACK_RIGHT             0x20
#	define SPEAKER_FRONT_LEFT_OF_CENTER   0x40
#	define SPEAKER_FRONT_RIGHT_OF_CENTER  0x80
#	define SPEAKER_BACK_CENTER            0x100
#	define SPEAKER_SIDE_LEFT              0x200
#	define SPEAKER_SIDE_RIGHT             0x400
#	define SPEAKER_TOP_CENTER             0x800
#	define SPEAKER_TOP_FRONT_LEFT         0x1000
#	define SPEAKER_TOP_FRONT_CENTER       0x2000
#	define SPEAKER_TOP_FRONT_RIGHT        0x4000
#	define SPEAKER_TOP_BACK_LEFT          0x8000
#	define SPEAKER_TOP_BACK_CENTER        0x10000
#	define SPEAKER_TOP_BACK_RIGHT         0x20000
#	define SPEAKER_RESERVED               0x80000000
#endif

#ifndef	WAVE_FORMAT_PCM
#	define	WAVE_FORMAT_PCM                0x0001
#endif
#ifndef	WAVE_FORMAT_IEEE_FLOAT
#	define	WAVE_FORMAT_IEEE_FLOAT         0x0003
#endif
#ifndef	WAVE_FORMAT_EXTENSIBLE
#	define	WAVE_FORMAT_EXTENSIBLE         0xfffe
#endif

enum {
	UNDEFINED = 0,
	DEFINED
} channel_config;

/* ********************************************************************************************************************
	Vorbis Channel Mapping

	Mono = Front Left.
	    In WAVEFORMATEXTENSIBLE = SPEAKER_FRONT_LEFT

	    so pcm[0] -> ogg[0]

	Stereo = Front Left, Front Right.
	    In WAVEFORMATEXTENSIBLE = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT

	    so pcm[0] -> ogg[0]
	       pcm[1] -> ogg{1]

	3 Channel = Front Left, Front Centre, Front Right.
	    In WAVEFORMATEXTENSIBLE = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER

	    so pcm[0] -> ogg[0]
	       pcm[1] -> ogg{2]
	       pcm{2] -> ogg[1]

	4 Channel = Front Left, Front Right, Rear Left, Rear Right
	    In WAVEFORMATEXTENSIBLE = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT

	    so pcm[0] -> ogg[0]
	       pcm[1] -> ogg{1]
	       pcm{2] -> ogg[2]
	       pcm{3] -> ogg[3]

	5 Channel = Front Left, Front Centre, Front Right, Rear Left, Rear Right
	    In WAVEFORMATEXTENSIBLE = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER
	                             | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT

	    so pcm[0] -> ogg[0]
	       pcm[1] -> ogg{2]
	       pcm{2] -> ogg[1]
	       pcm{3] -> ogg[3]
	       pcm{4] -> ogg[4]

	6 Channel = Front Left, Front Centre, Front Right, Rear Left, Rear Right, LFE
	    In WAVEFORMATEXTENSIBLE = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER
        	                     | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT

	    so pcm[0] -> ogg[0]
	       pcm[1] -> ogg{2]
	       pcm{2] -> ogg[1]
	       pcm{3] -> ogg[5]
	       pcm{4] -> ogg[3]
	       pcm{5] -> ogg[4]

	There are currently no other channel mappings specified in the Vorbis Spec as of 2005-11-26. So, any other
	channel configurations will be mapped in the order presented.

	And, vice-versa for decoding, of course.
******************************************************************************************************************** */

#ifdef _WIN32
# define POPEN_READ_BINARY_OPEN(cmd)    _popen ((cmd), "rb")
# define POPEN_WRITE_BINARY_OPEN(cmd)   _popen ((cmd), "wb")
# define PCLOSE(fp)                     _pclose(fp)
#else
# define POPEN_READ_BINARY_OPEN(cmd)    popen ((cmd), "r")
# define POPEN_WRITE_BINARY_OPEN(cmd)   popen ((cmd), "w")
# define PCLOSE(fp)                     pclose(fp)
#endif

// Path separator
#if defined __unix__  ||  defined __bsdi__  ||  defined __FreeBSD__  ||  defined __OpenBSD__  ||  defined __NetBSD__
# define PATH_SEP               '/'
# define DRIVE_SEP              '\0'
# define EXE_EXT                ""
# define DEV_NULL               "/dev/null"
#elif defined _WIN32  ||  defined __TURBOC__  ||  defined __ZTC__  ||  defined _MSC_VER
# define PATH_SEP               '\\'
# define DRIVE_SEP              ':'
# define EXE_EXT                ".exe"
# define DEV_NULL               "\\nul"
#else
# define PATH_SEP               '/'         // Amiga: C:/
# define DRIVE_SEP              ':'
# define EXE_EXT                ""
# define DEV_NULL               "nul"
#endif

int setup_resample(oe_enc_opt *opt);
void clear_resample(oe_enc_opt *opt);
void setup_downmix(oe_enc_opt *opt);
void clear_downmix(oe_enc_opt *opt);
void setup_scaler(oe_enc_opt *opt, float scale);
void clear_scaler(oe_enc_opt *opt);

typedef struct
{
	int (*id_func)(unsigned char *buf, int len); /* Returns true if can load file */
	int id_data_len; /* Amount of data needed to id whether this can load the file */
	int (*open_func)(FILE *in, oe_enc_opt *opt, unsigned char *buf, int buflen);
	void (*close_func)(void *);
	char *format;
	char *description;
} input_format;


typedef struct {
	unsigned short format;
	unsigned short channels;
	unsigned int channel_mask;
	unsigned int samplerate;
	unsigned int bytespersec;
	unsigned short align;
	unsigned short samplesize;
} wav_fmt;

typedef struct {
	short channels;
	int channel_map;
	short samplesize;
	long totalsamples;
	long samplesread;
	FILE *f;
	short bigendian;
        int *channel_permute;
} wavfile;

typedef struct {
	short channels;
	int totalframes;
	short samplesize;
	int rate;
	int offset;
	int blocksize;
} aiff_fmt;

typedef wavfile aifffile; /* They're the same */

input_format *open_audio_file(FILE *in, oe_enc_opt *opt);

int raw_open(FILE *in, oe_enc_opt *opt, unsigned char *buf, int buflen);
int wav_open(FILE *in, oe_enc_opt *opt, unsigned char *buf, int buflen);
int aiff_open(FILE *in, oe_enc_opt *opt, unsigned char *buf, int buflen);
int wav_id(unsigned char *buf, int len);
int aiff_id(unsigned char *buf, int len);
void wav_close(void *);
void raw_close(void *);

long wav_read(void *, float **buffer, int samples);
long wav_ieee_read(void *, float **buffer, int samples);
long raw_read_stereo(void *, float **buffer, int samples);

#ifdef __cplusplus
}
#endif

#endif /* __AUDIO_H */

